import serial
import time
import threading
import tkinter as tk
from datetime import datetime

class ZigBeeDataCollector:
    def __init__(self, port='COM1', baudrate=38400):
        self.port = port
        self.baudrate = baudrate
        self.serial_conn = None
        self.is_running = False
        self.data_thread = None
        # 用于存储最新数据（传感器名: 最新值）
        self.latest_data = {
            "温度": None,
            "湿度": None,
            "光照传感器电压": None,
            "红外传感器电平": None
        }

    def connect(self):
        try:
            self.serial_conn = serial.Serial(self.port, self.baudrate, timeout=1)
            print(f"成功连接到 {self.port}，波特率: {self.baudrate}")
            return True
        except Exception as e:
            print(f"连接串口失败: {e}")
            return False

    def disconnect(self):
        if self.serial_conn and self.serial_conn.is_open:
            self.serial_conn.close()
            print("串口连接已断开")

    def start_collecting(self):
        if not self.serial_conn or not self.serial_conn.is_open:
            if not self.connect():
                return False

        self.is_running = True
        self.data_thread = threading.Thread(target=self._collect_data)
        self.data_thread.daemon = True
        self.data_thread.start()
        print("开始收集数据...")
        return True

    def stop_collecting(self):
        self.is_running = False
        if self.data_thread and self.data_thread.is_alive():
            self.data_thread.join(timeout=1.0)
        print("数据收集已停止")

    def _collect_data(self):
        while self.is_running:
            try:
                if self.serial_conn.in_waiting:
                    # 读取原始字节并尝试 GBK 解码（匹配串口助手的中文）
                    line = self.serial_conn.readline()
                    try:
                        decoded_line = line.decode('gbk').strip()
                    except:
                        decoded_line = line.decode('latin-1').strip()

                    if decoded_line:
                        print(f"解码后数据: {decoded_line}")
                        # 解析数据并更新 latest_data
                        self.parse_and_update(decoded_line)
            except Exception as e:
                print(f"读取数据时出错: {e}")
                time.sleep(1)
            time.sleep(0.1)

    def parse_and_update(self, line):
        """解析串口数据，更新 latest_data"""
        # 示例：
        # 温湿度传感器（123），温度：28℃，湿度：70%
        # 光照传感器电压（123）：1.66V
        # 红外传感器电平（123）：1

        if "温度" in line and "湿度" in line:
            # 提取温度、湿度
            temp = self.extract_value(line, "温度：", "℃")
            hum = self.extract_value(line, "湿度：", "%")
            if temp:
                self.latest_data["温度"] = temp
            if hum:
                self.latest_data["湿度"] = hum

        elif "光照传感器电压" in line:
            volt = self.extract_value(line, "光照传感器电压（123）：", "V")
            if volt:
                self.latest_data["光照传感器电压"] = volt

        elif "红外传感器电平" in line:
            level = self.extract_value(line, "红外传感器电平（123）：", "")
            if level:
                self.latest_data["红外传感器电平"] = level

    def extract_value(self, line, prefix, suffix):
        """从字符串中提取数值（如从 "温度：28℃" 提取 28）"""
        start = line.find(prefix) + len(prefix)
        end = line.find(suffix, start)
        if start < len(prefix) or end == -1:
            return None
        return line[start:end].strip()

    def get_latest_data(self):
        """返回最新数据的格式化字符串"""
        output = []
        for sensor, value in self.latest_data.items():
            # 如果值为 None，显示“无数据”，否则显示值
            output.append(f"{sensor}：{value if value is not None else '无数据'}")
        return "\n".join(output) + "\n"


# ------------------- Tkinter 界面 -------------------
def update_gui():
    """更新 Tkinter 文本框内容"""
    data_str = collector.get_latest_data()
    text_widget.delete(1.0, tk.END)  # 清空文本框
    text_widget.insert(tk.END, data_str)
    # 1秒后再次更新（可根据需求调整频率）
    root.after(1000, update_gui)

if __name__ == "__main__":
    # 初始化串口采集器
    collector = ZigBeeDataCollector(port='COM1', baudrate=38400)

    # 启动数据采集
    if collector.start_collecting():
        # 创建 Tkinter 窗口
        root = tk.Tk()
        root.title("ZigBee 传感器数据显示")
        root.geometry("400x300")

        # 创建文本框用于显示数据
        text_widget = tk.Text(root, font=("SimSun", 12))
        text_widget.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)

        # 启动 GUI 更新
        update_gui()

        # 运行 Tkinter 主循环
        try:
            root.mainloop()
        finally:
            # 关闭程序时停止采集并断开串口
            collector.stop_collecting()
            collector.disconnect()